package com.danskin.wechat.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.danskin.wechat.api.client.DanskinCRMApiClient;
import com.danskin.wechat.constant.DanskinConstants;
import com.danskin.wechat.dao.CrmBrandInfoDao;
import com.danskin.wechat.dao.CustGiftRecordDao;
import com.danskin.wechat.dao.CustInfoDao;
import com.danskin.wechat.dao.CustInfoExDao;
import com.danskin.wechat.dao.CustPointRecordDao;
import com.danskin.wechat.dao.GiftConfigDao;
import com.danskin.wechat.dao.WxCardConfigDao;
import com.danskin.wechat.entity.CrmBrandInfo;
import com.danskin.wechat.entity.CustGiftRecord;
import com.danskin.wechat.entity.CustInfoEx;
import com.danskin.wechat.entity.CustInfoExView;
import com.danskin.wechat.entity.CustPointRecord;
import com.danskin.wechat.entity.GiftConfig;
import com.danskin.wechat.entity.WxCardConfig;
import com.danskin.wechat.entity.WxMediaPlatform;
import com.danskin.wechat.model.AccessResponse;
import com.danskin.wechat.service.GiftService;
import com.danskin.wechat.service.WechatMsgTemplateService;
import com.danskin.wechat.util.DateUtils;
import com.danskin.wechat.util.LogUtil;
import com.danskin.wechat.vo.CustInfoVo;

@Service
public class GiftServiceImpl implements GiftService {

	@Autowired
	private CustInfoDao custInfoDao;

	@Autowired
	private GiftConfigDao giftConfigDao;

	@Autowired
	private CustInfoExDao custInfoExDao;

	@Autowired
	private CrmBrandInfoDao crmBrandInfoDao;

	@Autowired
	private CustPointRecordDao custPointRecordDao;

	@Autowired
	private CustGiftRecordDao custGiftRecordDao;

	@Autowired
	private WxCardConfigDao wxCardConfigDao;

	@Autowired
	private WechatMsgTemplateService msgTemplateService;

	/**
	 * 获取活动奖品前的验证
	 * 
	 * @param wxOpenId
	 * @param activityType
	 * @return
	 * @author makunsmac
	 */
	public AccessResponse<String> validateGetActivityPrize(String wxOpenId, Integer activityType) {
		LogUtil.info("========验证活动抽奖参数：wxOpenId=" + wxOpenId + "&activityType=" + activityType);

		try {

			// 根据用户微信openId获取用户信息
			CustInfoVo custInfoDto = custInfoDao.queryCustInfoDtoByOpenId(wxOpenId);
			if (custInfoDto == null || StringUtils.isBlank(custInfoDto.getMemberId())) {
				return new AccessResponse<String>("-1", "获取用户信息异常");
			}

			CustInfoEx param = new CustInfoEx();
			param.setMemberId(custInfoDto.getMemberId());
			List<CustInfoEx> custInfoExList = custInfoExDao.selectCustInfoExList(param);

			// 如果活动是新人礼
			if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) {
				if (CollectionUtils.isEmpty(custInfoExList)) {
					return new AccessResponse<String>("-1", "获取用户信息异常");
				}
				// 验证用户是否已领取过奖品
				if (custInfoExList.get(0).getIsGetGift() == DanskinConstants.CUST_INFO_EX_IS_GET_GIFT_ALREADY_GET) {
					return new AccessResponse<String>("-1", "您已领取过奖品，请勿重复领取");
				}
			}

			// 根据活动类型获取该活动下的奖品
			List<GiftConfig> paramList = new ArrayList<GiftConfig>();
			List<GiftConfig> giftList = new ArrayList<GiftConfig>();
			GiftConfig giftConfig = new GiftConfig();
			giftConfig.setType(activityType);
			paramList = giftConfigDao.selectGiftConfigList(giftConfig);

			// 判断活动奖品配置为空
			if (CollectionUtils.isEmpty(paramList)) {
				custInfoExList.get(0).setIsGetGift(DanskinConstants.CUST_INFO_EX_IS_GET_GIFT_ALREADY_GET);
				custInfoExDao.updateCustInfoEx(custInfoExList.get(0));
				return new AccessResponse<String>("-1", "活动奖品配置为空");
			}

			// 剔除库存为0的奖品配置
			for (GiftConfig temp : paramList) {
				if (temp.getTotalQty() != null && temp.getUsedQty() != null) {
					if (temp.getTotalQty() > temp.getUsedQty()) {
						giftList.add(temp);
					}
				}
			}

			// 判断剔除库存为0的奖品后的配置为空
			if (CollectionUtils.isEmpty(giftList)) {
				custInfoExList.get(0).setIsGetGift(DanskinConstants.CUST_INFO_EX_IS_GET_GIFT_ALREADY_GET);
				custInfoExDao.updateCustInfoEx(custInfoExList.get(0));
				return new AccessResponse<String>("-1", "活动奖品配置信息中没有库存");
			}

			return new AccessResponse<String>("0", "验证正常");
		} catch (Exception e) {
			LogUtil.error("======获取活动奖品前的验证异常", e);
		}
		return new AccessResponse<String>("-1", "获取活动奖品前的验证异常");
	}

	/**
	 * 活动抽奖
	 * 
	 * @param wxOpenId
	 * @param activityType
	 * @return
	 * @author makunsmac
	 */
	@Override
	public Object getActivityPrize(String wxOpenId, Integer activityType, WxMediaPlatform mediaPlatform) {
		LogUtil.info("========活动抽奖参数：wxOpenId=" + wxOpenId + "&activityType=" + activityType);
		try {
			// 根据活动类型获取该活动下的奖品
			List<GiftConfig> paramList = new ArrayList<GiftConfig>();
			List<GiftConfig> giftList = new ArrayList<GiftConfig>();
			GiftConfig giftConfig = new GiftConfig();
			giftConfig.setMpId(mediaPlatform.getId());
			giftConfig.setType(activityType);
			paramList = giftConfigDao.selectGiftConfigList(giftConfig);

			// 剔除库存为0的奖品配置
			for (GiftConfig temp : paramList) {
				if (temp.getTotalQty() != null && temp.getUsedQty() != null) {
					if (temp.getTotalQty() > temp.getUsedQty() && temp.getProbability().intValue() > 0) {
						giftList.add(temp);
					}
				}
			}

			// 执行活动奖品领取操作
			giftConfig = executeLottery(giftList);
			if (giftConfig != null) {

				// 根据用户微信openId获取用户信息
				CustInfoExView custInfoDto = custInfoExDao.selectCustByOpenId(mediaPlatform.getId(), wxOpenId);

				// 判断用户领取到的是什么类型的奖品（门店优惠券、积分、实物）
				if (StringUtils.equals(giftConfig.getPrizeType(), DanskinConstants.GIFT_CONFIG_PRIZE_TYPE_COUPON)) { // 门店优惠券
					// 异步处理
					final GiftConfig gc = giftConfig;
					final CustInfoExView ciev = custInfoDto;
					final Integer at = activityType;
					new Thread(new Runnable() {
						@Override
						public void run() {
							// 处理门店优惠券
							try {
								dealCoupon(gc, ciev, at);
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}).start();

					// 根据giftConfig中的couponTemplateId查询wxCardConfig的名称、使用规则和优惠金额
					WxCardConfig param = new WxCardConfig();
					param.setTemplateId(giftConfig.getCouponTemplateId());
					List<WxCardConfig> wxCardConfigList = wxCardConfigDao.selectWxCardConfigList(param);
					if (CollectionUtils.isNotEmpty(wxCardConfigList)) {
						JSONObject cardConfigJSON = new JSONObject();
						cardConfigJSON.put("name", wxCardConfigList.get(0).getName());
						cardConfigJSON.put("ruleDesc", wxCardConfigList.get(0).getRuleDesc());
						cardConfigJSON.put("faceValue", wxCardConfigList.get(0).getFaceValue());
						cardConfigJSON.put("type", "coupon");
						return cardConfigJSON;
					}
					return null;

				} else if (StringUtils.equals(giftConfig.getPrizeType(),
						DanskinConstants.GIFT_CONFIG_PRIZE_TYPE_POINT)) { // 积分
					// 异步处理
					final GiftConfig gc = giftConfig;
					final CustInfoExView ciev = custInfoDto;
					final Integer at = activityType;
					final WxMediaPlatform wmpf = mediaPlatform;
					new Thread(new Runnable() {
						@Override
						public void run() {
							// 处理积分
							try {
								dealPoint(gc, ciev, at, wmpf);
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}).start();

					JSONObject pointJSON = new JSONObject();
					pointJSON.put("point", giftConfig.getPoints());
					pointJSON.put("type", "point");
					return pointJSON;

				} else if (StringUtils.equals(giftConfig.getPrizeType(),
						DanskinConstants.GIFT_CONFIG_PRIZE_TYPE_PRODUCT)) { // 实物
					// 处理实物
					Map<String, Object> resultMap = dealProduct(giftConfig, custInfoDto, activityType);
					if ((Boolean) resultMap.get("flag")) {
						CustGiftRecord goodsRecord = (CustGiftRecord) resultMap.get("custGiftRecord");
						JSONObject productJSON = new JSONObject();
						productJSON.put("id", goodsRecord.getId());
						productJSON.put("name", giftConfig.getName());
						productJSON.put("productImage", giftConfig.getPicUrl());
						productJSON.put("type", "product");
						return productJSON;
					} else {
						return null;
					}
				}
			}
		} catch (Exception e) {
			LogUtil.error("======新人礼领取异常---openId：" + wxOpenId, e);
		}
		return null;
	}

	/**
	 * 执行新人礼领取操作
	 * 
	 * @param giftConfigList
	 * @return
	 */
	private GiftConfig executeLottery2(List<GiftConfig> giftConfigList) {
		// 总的概率区间
		Double totalPro = 0.00;
		// 存储每个奖品新的概率区间
		List<Double> proSection = new ArrayList<Double>();
		proSection.add(0.00);
		// 遍历每个奖品，设置概率区间，总的概率区间为每个概率区间的总和
		for (GiftConfig award : giftConfigList) {
			// 每个概率区间为奖品概率乘以1000（把两位小数转换为整）再乘以剩余奖品数量
			totalPro += award.getProbability().doubleValue() * 10 * (award.getTotalQty() - award.getUsedQty());
			proSection.add(totalPro);
		}
		// 获取总的概率区间中的随机数
		Random random = new Random();
		float randomPro = random.nextInt(totalPro.intValue());
		// 判断取到的随机数在哪个奖品的概率区间中
		for (int i = 0, size = proSection.size(); i < size; i++) {
			if (randomPro >= proSection.get(i) && randomPro < proSection.get(i + 1)) {
				return giftConfigList.get(i);
			}
		}
		return null;
	}

	private GiftConfig executeLottery(List<GiftConfig> giftConfigList) {
		int sum = 0;
		for (GiftConfig award : giftConfigList) {
			sum = sum + award.getProbability().intValue();
		}
		for (GiftConfig award : giftConfigList) {
			int probability = award.getProbability().intValue();
			Random random = new Random();
			int rnd = random.nextInt(sum) + 1;
			if (rnd <= probability) {
				return award;
			} else {
				sum = sum - probability;
			}
		}
		return null;
	}

	/**
	 * 处理用户抽取到的门店优惠券（同步CRM、消耗库存）
	 * 
	 * @param giftConfig
	 * @param custId
	 * @return
	 * @author makunsmac
	 * @throws Exception
	 */
	private boolean dealCoupon(GiftConfig giftConfig, CustInfoExView custInfoDto, Integer activityType)
			throws Exception {
		String changeReason = "";

		// 根据公众号查询品牌
		CrmBrandInfo brandInfo = crmBrandInfoDao.selectByMpId(giftConfig.getMpId());

		DanskinCRMApiClient danskinCRMApiClient = DanskinCRMApiClient.createInstance();

		// 记录请求日志
		LogUtil.info("=======新人礼门店优惠券同步CRM参数：memberId=" + custInfoDto.getMemberId() + "&couponTemplateId="
				+ giftConfig.getCouponTemplateId());
		// 调用CRM接口同步积分
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) {
			changeReason = "新人礼领取优惠券";
		} else if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_THANKFUL) {
			changeReason = "感恩礼领取优惠券";
		}
		// 执行CRM请求发券
		JSONObject jCRMCouponResult = danskinCRMApiClient.sendCouponToCRM(custInfoDto.getMemberId(),
				giftConfig.getCouponTemplateId(), 1, changeReason, brandInfo.getBrandId());
		// 记录结果日志
		LogUtil.info("======新人礼门店优惠券同步CRM结果：" + jCRMCouponResult.toJSONString());

		if (jCRMCouponResult == null || !jCRMCouponResult.containsKey("status")
				|| jCRMCouponResult.getInteger("status") != 1) {
			return false;
		}

		// 创建领取详情
		CustGiftRecord param = new CustGiftRecord();
		param.setMpId(giftConfig.getMpId());
		param.setCustExId(custInfoDto.getId());
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) { // 新人礼
			param.setActivityName("新人礼");
		} else if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_THANKFUL) { // 感恩礼
			param.setActivityName("感恩礼");
		}
		param.setGiftConfigId(giftConfig.getId());
		param.setGoodsName(giftConfig.getName());
		param.setQuantity(1);
		param.setStatus(DanskinConstants.CUST_GOODS_RECODE_STATUS_ALREADY_GET);
		param.setCreatedTime(new Date());
		// 插入到领取记录表中
		custGiftRecordDao.insertCustGiftRecord(param);

		// 消费库存
		if (!updateGiftConfigQuantity(giftConfig)) {
			return false;
		}

		// 如果活动是新人礼，为了限制用户只能领取一次，
		// 当消费库存成功后更新用户扩展信息表中的is_get_gift为已领取
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) {
			if (!judgeAndUpdateIsGetGift(custInfoDto)) {
				return false;
			}
		}

		return true;
	}

	/**
	 * 处理用户抽取到的积分（同步CRM、消耗库存以及创建领取详情，其中领取详情的状态为已领取）
	 * 
	 * @param giftConfig
	 * @param custInfo
	 * @return
	 * @author makunsmac
	 * @throws Exception
	 */
	private boolean dealPoint(GiftConfig giftConfig, CustInfoExView custInfoDto, Integer activityType,
			WxMediaPlatform mediaPlatform) throws Exception {
		String changeReason = "";

		// 变更流水号
		String changeId = "XR_" + DateUtils.formatMillTime();

		// 根据公众号查询品牌
		CrmBrandInfo brandInfo = crmBrandInfoDao.selectByMpId(giftConfig.getMpId());

		DanskinCRMApiClient danskinCRMApiClient = DanskinCRMApiClient.createInstance();

		// 记录请求日志
		LogUtil.info("======新人礼积分同步CRM参数：changeId=" + changeId + "&memberId=" + custInfoDto.getMemberId() + "&mobile="
				+ custInfoDto.getMobile() + "&points=" + giftConfig.getPoints());
		// 调用CRM接口同步积分
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) {
			changeReason = "新人礼领取积分";
		} else if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_THANKFUL) {
			changeReason = "感恩礼领取积分";
		}
		JSONObject jCRMPointResult = danskinCRMApiClient.sendPointToCRM(changeId, custInfoDto.getMemberId(),
				custInfoDto.getMobile(), Float.valueOf(giftConfig.getPoints() + ""), changeReason,
				brandInfo.getBrandId());
		// 记录返回日志
		LogUtil.info("======活动积分同步CRM结果：" + jCRMPointResult.toJSONString());

		if (jCRMPointResult == null || !jCRMPointResult.containsKey("status")
				|| jCRMPointResult.getInteger("status") != 1) {
			return false;
		}

		// 创建领取详情
		CustGiftRecord giftRecordParam = new CustGiftRecord();
		giftRecordParam.setMpId(giftConfig.getMpId());
		giftRecordParam.setCustExId(custInfoDto.getId());
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) { // 新人礼
			giftRecordParam.setActivityName("新人礼");
		} else if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_THANKFUL) { // 感恩礼
			giftRecordParam.setActivityName("感恩礼");
		}
		giftRecordParam.setGiftConfigId(giftConfig.getId());
		giftRecordParam.setGoodsName(giftConfig.getName());
		giftRecordParam.setQuantity(1);
		giftRecordParam.setStatus(DanskinConstants.CUST_GOODS_RECODE_STATUS_ALREADY_GET);
		giftRecordParam.setCreatedTime(new Date());
		// 插入到领取记录表中
		custGiftRecordDao.insertCustGiftRecord(giftRecordParam);

		// 消费库存
		if (!updateGiftConfigQuantity(giftConfig)) {
			return false;
		}

		// 创建领取详情
		CustPointRecord param = new CustPointRecord();
		param.setCustExId(custInfoDto.getId());
		param.setPoints(giftConfig.getPoints());
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) {
			param.setSource("新人礼");
		} else if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_THANKFUL) {
			param.setSource("感恩礼");
		}
		param.setGetTime(new Date());
		// 积分过期时间为次年12月31号
		param.setExpiredTime(DateUtils.getNextYear());
		param.setMemberId(custInfoDto.getMemberId());
		param.setCreatedTime(new Date());
		// 获取当前用户可用积分
		// CustInfoEx custInfoEx =
		// custInfoExDao.selectByCustId(giftConfig.getMpId(),
		// custInfoDto.getId());
		// 如果custInfoEx不为空并且可用积分不为空
		if (custInfoDto != null && custInfoDto.getAvaPoints() != null) {
			param.setAvaPoints(custInfoDto.getAvaPoints() + giftConfig.getPoints());
			custInfoDto.setAvaPoints(custInfoDto.getAvaPoints() + giftConfig.getPoints());
		}
		// 如果custInfoEx不为空并且总积分不为空
		if (custInfoDto != null && custInfoDto.getTotalPoints() != null) {
			param.setTotalPoints(custInfoDto.getTotalPoints() + giftConfig.getPoints());
			custInfoDto.setTotalPoints(custInfoDto.getTotalPoints() + giftConfig.getPoints());
		}
		// 变更流水号
		param.setChangeId(changeId);

		if (brandInfo != null && brandInfo.getId() != null) {
			param.setBrandId(brandInfo.getId());
		}

		// 更新cust_info_ex表中的用户可用积分以及总积分
		if (custInfoExDao.updateCustInfoEx(custInfoDto) == 0) {
			return false;
		}

		// 如果活动是新人礼，为了限制用户只能领取一次，
		// 当消费库存成功后更新用户扩展信息表中的is_get_gift为已领取
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) {
			if (!judgeAndUpdateIsGetGift(custInfoDto)) {
				return false;
			}
		}

		// 判断执行新建领取详情是否成功
		if (custPointRecordDao.insertCustPointRecord(param) > 0) {
			// 调用积分变动消息模版通知接口
			msgTemplateService.sendCustChangePointsMsg(mediaPlatform.getAccessToken(), mediaPlatform.getAppId(),
					custInfoDto.getWxOpenId(), custInfoDto.getName(), custInfoDto.getMobile(), giftConfig.getPoints(),
					custInfoDto.getAvaPoints());
			return true;
		} else {
			return false;
		}

	}

	/**
	 * 处理用户抽取到的实物（消耗库存以及创建领取详情，其中领取详情的状态为未领取）
	 * 
	 * @param giftConfig
	 * @param custInfo
	 * @return
	 * @author makunsmac
	 * @throws Exception
	 */
	private Map<String, Object> dealProduct(GiftConfig giftConfig, CustInfoExView custInfoDto, Integer activityType)
			throws Exception {
		Map<String, Object> resultMap = new HashMap<String, Object>();

		// 消费库存
		if (!updateGiftConfigQuantity(giftConfig)) {
			resultMap.put("flag", false);
			return resultMap;
		}

		// 创建领取详情
		CustGiftRecord param = new CustGiftRecord();
		param.setMpId(giftConfig.getMpId());
		param.setCustExId(custInfoDto.getId());
		param.setActivityName("新人礼");
		param.setGiftConfigId(giftConfig.getId());
		param.setGoodsName(giftConfig.getName());
		param.setGoodsPicUrl(giftConfig.getPicUrl());
		param.setQuantity(1);
		param.setStatus(DanskinConstants.CUST_GOODS_RECODE_STATUS_NOT_GET);
		param.setCreatedTime(new Date());

		// 如果活动是新人礼，为了限制用户只能领取一次，
		// 当消费库存成功后更新用户扩展信息表中的is_get_gift为已领取
		if (activityType == DanskinConstants.GIFT_CONFIG_TYPE_NEW_CUST) {
			if (!judgeAndUpdateIsGetGift(custInfoDto)) {
				resultMap.put("flag", false);
				return resultMap;
			}
		}

		// 判断执行新建领取详情是否成功
		Integer custGiftRecordId = custGiftRecordDao.insertCustGiftRecord(param);
		if (custGiftRecordId != 0) {
			resultMap.put("flag", true);
			resultMap.put("custGiftRecord", param);
			return resultMap;
		} else {
			resultMap.put("flag", true);
			return resultMap;
		}
	}

	/**
	 * 为了限制用户只能领取一次 当消费库存成功后更新用户扩展信息表中的is_get_gift为已领取
	 * 
	 * @param custInfoDto
	 * @return
	 * @author makunsmac
	 * @throws Exception
	 */
	private boolean judgeAndUpdateIsGetGift(CustInfoExView custInfoDto) throws Exception {
		CustInfoEx param = new CustInfoEx();
		try {
			param.setMemberId(custInfoDto.getMemberId());
			List<CustInfoEx> custInfoExList = custInfoExDao.selectCustInfoExList(param);

			if (CollectionUtils.isEmpty(custInfoExList)) {
				return false;
			}

			if (custInfoExList.get(0).getIsGetGift() == DanskinConstants.CUST_INFO_EX_IS_GET_GIFT_ALREADY_GET) {
				return false;
			}

			// 如果用户扩展信息不为空并且领取状态不为已领取，就更新为已领取
			CustInfoEx custInfoEx = custInfoExList.get(0);
			custInfoEx.setIsGetGift(DanskinConstants.CUST_INFO_EX_IS_GET_GIFT_ALREADY_GET);
			if (custInfoExDao.updateCustInfoEx(custInfoEx) == 0) {
				return false;
			}
		} catch (Exception e) {
			throw e;
		}
		return true;
	}

	/**
	 * 同步更新新人礼库存
	 * 
	 * @param giftConfig
	 * @return
	 * @throws Exception
	 */
	private synchronized boolean updateGiftConfigQuantity(GiftConfig giftConfig) throws Exception {
		try {
			giftConfig.setUsedQty(giftConfig.getUsedQty() + 1);
			if (giftConfigDao.updateGiftConfig(giftConfig) > 0) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			throw e;
		}
	}

}
